package com.scalar.chiptrack.adaptor.ikanos.fab;

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import com.scalar.ScalarException;
import com.scalar.chiptrack.adaptor.AdaptorConstants;
import com.scalar.chiptrack.adaptor.AdaptorUtils;
import com.scalar.chiptrack.adaptor.utils.Parser;
import com.scalar.chiptrack.adaptor.utils.ParserFactory;
import com.scalar.chiptrack.adaptor.utils.ParserResult;
import com.scalar.chiptrack.adaptor.utils.XLSParserImpl;
import com.scalar.chiptrack.db.DataSource;
import com.scalar.chiptrack.jobs.JobHandler;
import com.scalar.chiptrack.utils.ConfigManager;
import com.scalar.chiptrack.utils.Logger;

public class FabParameterParser  extends JobHandler implements AdaptorConstants
{
    private Logger m_parserLogger       = null;
    private String m_dataOutputDir      = null;

    public  FabParameterParser() throws ScalarException
    {
        try
        {
            m_dataOutputDir = ConfigManager.getFabFileDir();

            if ( m_dataOutputDir != null )
            {
                AdaptorUtils.makeAllAdaptorDirs( m_dataOutputDir );

                m_parserLogger= AdaptorUtils.getDataParserLogger( m_dataOutputDir,"fab" );

                AdaptorUtils.setLogger( m_parserLogger );

            }
        }
        catch ( Exception se )
        {
            log( "ERROR!! ERROR!! ERROR!! Exception while loading FAB output directory details from database, Exception: " + se );
            System.out.println( "ERROR!! ERROR!! ERROR!! Exception while loading FAB output directory details from database, Exception: " + se );
        }
    }
    public static void main( String args[] ) throws Exception
    {
        try
        {
            new FabParameterParser().execute();
        }
        catch ( Exception e )
        {
            throw e;
        }
    }
    public void execute() throws Exception
    {
        AdaptorUtils.printHeader( "FAB", CONSTANT_PARSER );

        File doneDestDir = new File( m_dataOutputDir + "/done" );
        File dataoutDir  = new File( m_dataOutputDir );

        File[] fileList = dataoutDir.listFiles();

        if ( ( fileList == null ) || (fileList.length <= 3))
        {
            log("No file found in directory: " + dataoutDir);
            System.out.println("No file found in directory: " + dataoutDir );
            throw new ScalarException("No file found in directory: " + dataoutDir+ "----\n\n" );
        }

        ArrayList<File> successFileList = new ArrayList<File>();

        boolean success = false;

        for ( int i = 0; i < fileList.length; i++ )
        {
            if ( fileList[i].isDirectory() )
            {
                continue;
            }

            try
            {
                if ( fileList[i].getName().startsWith( FabParameterAdaptor.FILE_NAME )  || fileList[i].getName().indexOf( FabParameterAdaptor.FILE_NAME )  != -1)
                {
                     ArrayList<WaferDetail> fabList = parseFabReport( fileList[i].getAbsolutePath() );

                     if ( fabList != null && fabList.size() > 0 )
                     {
                         saveWaferDetails( fabList );
                     }

                    successFileList.add(fileList[i]);
                }

                success = true;
            }
            catch (Exception e)
            {
                success = false;
                log("Exception while parsing file: " + fileList[i].getAbsolutePath() + "\nException: " + e);
                e.printStackTrace();
                throw e;
            }
        }

        //int adaptor_id = AdaptorRunInfo.getLastRunAdaptorId( POAdaptor.ADAPTOR_NAME, CONSTANT_ADAPTOR);
        // transaction 9
        /*try
        {
            if (success)
            {
                AdaptorRunInfo.saveAdaptorLastUpdatedStatus(CONSTANT_PARSER, POAdaptor.ADAPTOR_NAME, CONSTANT_SUCCESS, adaptor_id);
                System.out.println("SUCCESSFULLY UPDATED IN THE DATABASE");
            }
        }
        catch (ScalarException se)
        {
            success = false;  //As filES DATA SAVED , UPDATEING AS SUCCESS
            AdaptorRunInfo.saveAdaptorLastUpdatedStatus(CONSTANT_PARSER, POAdaptor.ADAPTOR_NAME, CONSTANT_SUCCESS, adaptor_id);
            log("WARNING!! WARNING!! WARNING!! Could not update Adaptor run information, Exception: " + se);
            throw se;
        }*/

        // Step 10
        // Move the successful files to 'done' directory
        if (success)
        {
            AdaptorUtils.moveFilesToDone( successFileList, doneDestDir);
        }
    }
    
    public static void saveWaferDetails( ArrayList<WaferDetail> fabList ) throws ScalarException
    {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        WaferDetail waferDetail = null;
        boolean success = false;

        try
        {
            conn = DataSource.getConnection();

            pstmt = conn.prepareStatement ("{ CALL SP_CREATE_UPDATE_WAFER_DETAILS( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?,? ) }");

            int size = fabList.size();

            for(int i=0; i<size; i++)
            {
            	waferDetail = fabList.get( i );
                pstmt.setString (1, waferDetail.getPartNumber() );
                pstmt.setString (2, waferDetail.getShortName() );
                pstmt.setString (3, waferDetail.getPlannerCode() );
                pstmt.setString (4, waferDetail.getProductFunction() );
                pstmt.setString (5, waferDetail.getProcessGeometry() );
                pstmt.setString (6, waferDetail.getProductStatus() );
                pstmt.setString (7, waferDetail.getChipSizeX() );
                pstmt.setString (8, waferDetail.getChipSizeY() );
                pstmt.setString (9, waferDetail.getWaferThickness() );
                pstmt.setString (10, waferDetail.getDieSize() );
                pstmt.setString (11, waferDetail.getFabCycleTime() );
                pstmt.setString (12, waferDetail.getMaskServiceType() );
                pstmt.setString (13, waferDetail.getProcess() );
                pstmt.setString (14, waferDetail.getWaferSize() );
                pstmt.setString (15, waferDetail.getMetalLayers() );
                pstmt.setString (16, waferDetail.getPolyLayers() );
                pstmt.setString (17, waferDetail.getEpitaxial() );
                pstmt.setString (18, waferDetail.getNoofMaskLayers() );
                pstmt.setString (19, waferDetail.getFabCountry() );
                pstmt.setString (20, waferDetail.getOperatingVoltage() );
                pstmt.setString (21, waferDetail.getProductType() );
                pstmt.setString (22, waferDetail.getImplantCapacitor() );
                pstmt.setString (23, waferDetail.getStdCost1() );
                pstmt.setString (24, waferDetail.getStdCost2() );
                pstmt.setString (25, waferDetail.getStdCost3() );
                pstmt.setString (26, waferDetail.getStdCost4() );
                pstmt.setInt    (27, waferDetail.getGDPW() );

                pstmt.addBatch();
            }

            pstmt.executeBatch();

            success = true;
        }

        catch (Exception sqle)
        {
            sqle.printStackTrace();
            throw new ScalarException ("Could not Save Wafer information", sqle);
        }

        finally
        {
            try
            {
                if (conn != null)
                {
                    if (success == true)
                    {
                        conn.commit();
                    }
                    else
                    {
                        conn.rollback();
                    }
                }
            }
            catch (SQLException ignore) {}
            if(rs != null)
            {
                try
                {
                    rs.close();
                }
                catch(SQLException ignore){}
            }
            if (pstmt != null)
            {
                try
                {
                    pstmt.close();
                }
                catch (SQLException ignore){}
            }
            if (conn != null)
            {
                try
                {
                    conn.close();
                }
                catch (SQLException ignore){}
            }
        }
    }

    private ArrayList<WaferDetail> parseFabReport (String fileName ) throws Exception
    {
        if ( fileName == null ) throw new ScalarException( "Filename argument is null" );

        ParserResult result = null;
        ArrayList<WaferDetail> fabList = new ArrayList<WaferDetail>();
        WaferDetail waferDetail = null;
        try
        {
            File fabFile = new File( fileName );
            if ( !fabFile.exists() )
            {
                throw new ScalarException( fileName + " doesnt exist" );
            }

            Parser parser = ParserFactory.getXLSParser( fabFile );

            ((XLSParserImpl)parser).setHeaderRowIdx(0);
            ((XLSParserImpl)parser).setDataStartRowIdx(1);

            result = parser.parse();
            System.out.println("result = " + result.getHeadings() );
            System.out.println("String result = " + (String)result.getHeadings().get(27) );
            while ( result.next() )
            {
            	waferDetail = new WaferDetail();
            	waferDetail.setPartNumber( result.getString( "Wafer Part" ) );
            	waferDetail.setShortName( result.getString( "Short Names" ) );
            	waferDetail.setPlannerCode( result.getString( "Planner Code" ) );
               	waferDetail.setProductFunction( result.getString( "Product function" ) );
            	waferDetail.setProcessGeometry( result.getString( "Process Geometry" ) );
            	waferDetail.setProductStatus( result.getString( "Product Status" ) );
            	waferDetail.setChipSizeX( result.getString( "Chip Size X" ) );
            	waferDetail.setChipSizeY( result.getString( "Chip Size Y" ) );
            	waferDetail.setWaferThickness( result.getString( "Wafer thickness" ) );
            	waferDetail.setDieSize( result.getString( "Die Size" ) );
            	waferDetail.setFabCycleTime( result.getString( "Fab Cycle Time" ) );
            	waferDetail.setMaskServiceType( result.getString( "Mask Service Type" ) );
            	waferDetail.setProcess( result.getString( "Process" ) );
            	waferDetail.setWaferSize( result.getString( "Wafer Size (Inch)" ) );
            	waferDetail.setMetalLayers( result.getString( "Metal Layers" ) );
            	waferDetail.setPolyLayers( result.getString( "Poly Layers" ) );
            	waferDetail.setEpitaxial( result.getString( "Epitaxial" ) );
            	waferDetail.setNoofMaskLayers( result.getString( "# of Mask Layers" ) );
            	waferDetail.setFabCountry( result.getString( "Fab Country" ) );
            	waferDetail.setOperatingVoltage( result.getString( "Operating voltage" ) );
            	waferDetail.setProductType( result.getString( "Product type" ) );
            	waferDetail.setImplantCapacitor( result.getString( "Implant capacitor" ) );
                waferDetail.setStdCost1( result.getString( 24 ) );
                waferDetail.setStdCost2( result.getString( 25 ) );
                waferDetail.setStdCost3( result.getString( 26 ) );
            	waferDetail.setStdCost4( result.getString( 27 ) );
            	waferDetail.setGDPW( result.getInt( "GDPW" ) );
            	fabList.add( waferDetail );
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
            throw e;
        }
        
        //System.out.println("FAb List Size " + fabList.size());
        return  fabList;
    }

    private void log( String message )
    {
      if ( message == null ) return;

      if ( m_parserLogger != null )
      {
          m_parserLogger.logDebug( message + LINE_SEPARATOR );
      }
      else
      {
          System.out.println( message );
      }
    } // end of log method

}
